#pragma once

#include "dsegen.h"

#include <limits.h>
#include <math.h>

namespace dhis
{

#ifndef PI
#define PI 3.14159265358979323846
#endif

#define HALF_P1 1.57079632679489661923

#define FOUR_PI 12.56637061435917295384

#define EPSILON 1e-6

#define DEFAULT_SCALE 1.0
#define DEFAULT_OFFSET 0.0

#ifndef MAX
#  define MIN(a,b)      ((a<b) ? a : b)
#  define MAX(a,b)      ((a>b) ? a : b)
#endif


	//------------------------------------------------------------------------------
	typedef std::vector<int>                     IntVec;
	typedef std::vector<bool>                  BoolVec;
	typedef std::vector<REAL>                 REALVec;

	//------------------------------------------------------------------deg2rad
	inline REAL deg2rad(REAL deg)
	{
		return deg * PI / 180.0;
	}

	//------------------------------------------------------------------rad2deg
	inline REAL rad2deg(REAL rad)
	{
		return rad * 180.0 / PI;
	}

	//------------------------------------------------------------------iround
	inline int iround(REAL v)
	{
		return int((v < 0.0) ? v - 0.5 : v + 0.5);
	}

	//------------------------------------------------------------------uround
	inline int uround(REAL v)
	{
		return unsigned(v + 0.5);
	}

	//------------------------------------------------------------------ufloor
	inline unsigned ufloor(REAL v)
	{
		return unsigned(v);
	}

	//------------------------------------------------------------------uceil
	inline unsigned uceil(REAL v)
	{
		return unsigned(ceil(v));
	}

	//------------------------------------------------------------------pround
	inline void pround(REAL& value, const int& numberOfPrecisions)
	{
		int p = pow(10.0, numberOfPrecisions);
		value = (int)(value * p + 0.5) / (REAL)p;
	}

	//------------------------------------------------------------------------------
	class CRectI {
	public:
		static bool Intersect( CRectI& c, const CRectI& a, const CRectI& b);
		static bool Union( CRectI& c,  const CRectI& a, const CRectI& b);
	public:
		CRectI();
		CRectI( int x, int y, int width, int height);
		CRectI* Clone() const;
		void GetBounds( CRectI* rect) const;
		int GetLeft() const;
		int GetTop() const;
		int GetRight() const;
		int GetBottom() const;
		bool IsEmptyArea() const;
		bool Equals( const CRectI & rect) const;
		bool Contains( int x, int y) const;
		bool Contains( CRectI& rect) const;
		void Inflate( int dx,  int dy);
		bool Intersect( const CRectI& rect);
		bool IntersectsWith( const CRectI& rect) const;
		void Offset( int dx, int dy);
	public:
		int X;
		int Y;
		int Width;
		int Height;
	};

	//------------------------------------------------------------------------------
	class CIndex {
	public:
		CIndex(void);
		CIndex(const int& row,const int& col);
		CIndex(const CIndex& other);
		CIndex& operator=(const CIndex& other);
		bool operator==(const CIndex& other) const;
		bool operator!=(const CIndex& other) const;
		~CIndex(void);
	public:
		int m_row;
		int m_col;
	};

}